<?php

namespace App\Http\Controllers\Admin\Finance;

use App\Exports\PayBillOrderExport;
use App\Http\Controllers\Admin\Examine\Record;
use App\Http\Controllers\Controller;
use App\Models\AgentModel;
use App\Models\airline\base\RouteModel;
use App\Models\TakeOrderModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\airline\base\FlightModel as BaseFlightModel;
use App\Models\examine\RecordDetailModel;
use App\Models\examine\RecordModel;
use App\Models\PayBillIdsModel;
use App\Models\PayBillModel;
use App\Models\PayBillTicketModel;
use App\Models\TakeOrderPayModel;
use App\Models\TakeOrderRecModel;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

class PayBill extends Controller
{

    public function list(Request $request) {
        $page = $request->input('page', 1);
        $limit = $request->input('limit', 10);

        $bill_status = $request->input('bill_status', 0);
        $keyword = $request->input('keyword', '');
        $create_user = $request->input('create_user', '');
        $startTime = $request->input('startTime', '');
        $endTime = $request->input('endTime', '');

        $query = PayBillModel::query();

        if($keyword) {
            $query->where(function ($query) use ($keyword) {
                $query->where('sn', $keyword)
                ->orWhereIn('agent_id', function($query) use ($keyword) {
                    $query->select('id')->from((new AgentModel())->getTable())
                        ->where('name', 'like', '%'.$keyword.'%');
                });
            });
        }

        if($bill_status) {
            $query->where('status', $bill_status);
        }

        if($create_user) {
            $query->where('created_admin_id', $create_user);
        }

        if($startTime) {
            $query->where('created_at', '>=', $startTime);
        }

        if($endTime) {
            $query->where('created_at', '<=', $endTime);
        }

        $total = $query->count('id');
        $items = $query
            ->offset(($page-1) * $limit)
            ->limit($limit)
            ->orderBy('id', 'desc')
            ->get();

        $auth = $request->get('auth');
        $list = $items->map(function ($item) use ($auth) {
            $examine_detail = RecordDetailModel::where('record_id', $item->examine_record_id)
                ->where('admin_id', $auth->id)
                ->where('status', 1)
                ->where('is_examine', 1)
                ->first();

            $operate = [
                'submit' => $item->status == PayBillModel::STATUS_WAIT_SUBMIT,
                'review' => $examine_detail ? true : false,
                'edit' => $item->status == PayBillModel::STATUS_WAIT_AUDIT,
            ];
            return [
                'id' => $item->id,
                'sn' => $item->sn,
                'agent_name' => $item->agent->name ?? '',
                'type' => AgentModel::TYPE_LIST[$item->agent->type??''] ?? '',
                'currency' => $item->currency,
                'amount' => $item->amount,
                'actual_amount' => $item->actual_amount,
                'created_at' => $item->created_at->toDateTimeString(),
                'peroid' => $item->start . ' 至 ' . $item->end,
                'take_order_count' => $item->take_order_ids->count(),
                'status' => PayBillModel::STATUS_MAPS[$item->status],
                'ticket_status' => PayBillModel::TICKET_STATUS_MAPS[$item->ticket_status],
                'create_user' => $item->create_admin->staff->name ?? '',
                'remark' => $item->remark,
                'operate' => $operate,
            ];
        });

        return $this->success(['list' => $list, 'total' => $total]);
    }

    public function export(Request $request) {
        $bill_status = $request->input('bill_status', 0);
        $keyword = $request->input('keyword', '');
        $create_user = $request->input('create_user', '');
        $startTime = $request->input('startTime', '');
        $endTime = $request->input('endTime', '');

        $query = PayBillModel::query();

        if($keyword) {
            $query->where(function ($query) use ($keyword) {
                $query->where('sn', $keyword)
                ->orWhereIn('agent_id', function($query) use ($keyword) {
                    $query->select('id')->from((new AgentModel())->getTable())
                        ->where('name', 'like', '%'.$keyword.'%');
                });
            });
        }

        if($bill_status) {
            $query->where('status', $bill_status);
        }

        if($create_user) {
            $query->where('created_admin_id', $create_user);
        }

        if($startTime) {
            $query->where('created_at', '>=', $startTime);
        }

        if($endTime) {
            $query->where('created_at', '<=', $endTime);
        }

        $items = $query->orderBy('id', 'desc')->get();

        $list = $items->map(function ($item) {
            return [
                'sn' => $item->sn,
                'agent_name' => $item->agent->name ?? '',
                'type' => AgentModel::TYPE_LIST[$item->agent->type??''] ?? '',
                'currency' => $item->currency,
                'amount' => $item->amount,
                'actual_amount' => $item->actual_amount,
                'created_at' => $item->created_at->toDateTimeString(),
                'peroid' => $item->start . ' 至 ' . $item->end,
                'take_order_count' => $item->take_order_ids->count(),
                'status' => PayBillModel::STATUS_MAPS[$item->status],
                'ticket_status' => PayBillModel::TICKET_STATUS_MAPS[$item->ticket_status],
                'create_user' => $item->create_admin->staff->name ?? '',
                'remark' => $item->remark,
            ];
        });

        return Excel::download(new PayBillOrderExport(collect($list)), '应付账单.xlsx');
    }

    //提交审批
    public function submit(Request $request, $id) {
        $bill = PayBillModel::find($id);
        if (!$bill) {
            return $this->error('账单不存在');
        }

        if($bill->status != PayBillModel::STATUS_WAIT_SUBMIT) {
            return $this->error('账单状态错误');
        }

        DB::transaction(function() use ($bill){
            $bill->status = PayBillModel::STATUS_WAIT_AUDIT;
            $bill->examine_record_id = (new Record)->add(5);
            $bill->save();
        });

        return $this->success();
    }

    // 审核通过
    public function pass(Request $request, $id){
        $bill = PayBillModel::find($id);
        if (!$bill) {
            return $this->error('数据不存在');
        }

        if($bill->status != PayBillModel::STATUS_WAIT_AUDIT)  {
            return $this->error('账单不是待审核状态');
        }

        $record = RecordModel::find($bill->examine_record_id);
        if(!$record){
            return $this->error('数据不存在');
        }

        $auth = $request->get('auth');
        DB::beginTransaction();
        try {
            RecordDetailModel::where('record_id', $record->id)
                ->where('admin_id', $auth->id)
                ->update([
                    'status' => 2,
                    'examine_time' => date('Y-m-d H:i:s')
                ]);

            $record_pass = false;
            switch ($record->examine_type) {
                case 1:  //依次审批
                    $find_next = RecordDetailModel::where('record_id', $record->record_id)
                        ->where('is_examine', 0)
                        ->orderBy('sort')
                        ->first();
                    if($find_next){
                        $find_next->is_examine = 1;
                        $find_next->save();
                    } else {
                        $record_pass = true;
                    }
                    break;
                case 2:
                    $record_pass = true;
                    break;
                case 3:
                    $find_else = RecordDetailModel::where('record_id', $record->record_id)
                        ->where('status', 1)->first();
                    if(!$find_else){
                        $record_pass = true;

                    }
                    break;
            }

            if($record_pass){
                $record->status = 2;
                $record->save();

                $bill->status = PayBillModel::STATUS_WAIT_PAY;
                $bill->save();
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }

        return $this->success();
    }

    //审核驳回
    public function reject(Request $request, $id){
        $bill = PayBillModel::find($id);
        if (!$bill) {
            return $this->error('数据不存在');
        }

        if($bill->status != PayBillModel::STATUS_WAIT_AUDIT)  {
            return $this->error('账单不是待审核状态');
        }

        $auth = $request->get('auth');

        $params = $request->all();
        $rd = RecordDetailModel::where('admin_id', $auth->id)
            ->where('record_id', $bill->examine_record_id)
            ->first();;
        if(!$rd) {
            return $this->error('不能审核');
        }

        $record = RecordModel::find($rd->record_id);
        if(!$record){
            return $this->error('数据不存在');
        }
        DB::beginTransaction();
        try {
            $rd->status = 3;
            $rd->examine_time = date('Y-m-d H:i:s');
            $rd->examine_remarks = $params['reason'] ?? '';
            $rd->save();

            $record->status = 3;
            $record->reason = $params['reason'] ?? '';
            $record->save();

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage());
        }

        return $this->success();

    }

    //详情
    public function detail(Request $request, $id) {
        $bill = PayBillModel::with(['agent', 'create_admin'])->find($id);
        if(!$bill) {
            return $this->error('账单不存在');
        }

        $base = [
            'id' => $bill->id,
            'agent_name' => $bill->agent->name ?? '',
            'sn' => $bill->sn,
            'type' => AgentModel::TYPE_LIST[$bill->agent->type??''] ?? '',
            'take_order_count' => $bill->take_order_ids->count(),
            'currency' => $bill->currency,
            'amount' => $bill->amount,
            'status' => PayBillModel::STATUS_MAPS[$bill->status],
            'ticket_status' => PayBillModel::TICKET_STATUS_MAPS[$bill->ticket_status],
            'remark' => $bill->remark,
            'create_user' => $bill->create_admin->staff->name ?? '',
            'created_at' => $bill->created_at->toDateTimeString(),
            'peroid' => $bill->start . ' 至 ' . $bill->end,
        ];

        $take_orders = TakeOrderModel::whereIn('id', $bill->take_order_ids->pluck('take_order_id'))
            ->with(['orders'])
            ->get();

        return $this->success([
            'base' => $base,
            'review' => (new Record())->examine_info($bill->examine_record_id),
            'ticket' => $bill->ticket->map(function($item){
                return [
                    'id' => $item->id,
                    'type' => PayBillTicketModel::TYPE_MAPS[$item->type],
                    'amount' => $item->amount,
                    'annex' => $item->annex,
                    'create_user' => $item->create_admin->staff->name ?? '',
                    'created_at' => $item->created_at->toDateTimeString(),
                ];
            }),
            'take_orders' => $take_orders->map(function($item) use ($bill){
                $split_order_count = 0;
                foreach($item->orders as $order) {
                    $split_order_count += $order->split_order_addr->count();
                } 

                $routes = RouteModel::whereIn('id', $item->flight->items->pluck('route_id'))
                    ->pluck('name')->toArray();

                $flight_no = BaseFlightModel::whereIn('id', $item->flight->items->pluck('airline_flight_id'))
                    ->pluck('flight_number')->toArray();
                return [
                    'id' => $item->id,
                    'sn' => $item->sn,
                    'slipt_order_count' => $split_order_count,
                    'order_count' => $item->orders->count(),
                    'reality_weight' => $item->reality_weight,
                    'route' => implode(',', $routes),
                    'flight_no' => implode(',', $flight_no),
                    'status_name' => TakeOrderModel::STATUS_MAPS[$item->status] ?? '',
                    'currency' => $bill->currency,
                    'amount' => $bill->amount,
                    'take_off_time' => $item->flight->take_off_time ?? '',
                    'created_at' => $item->created_at->toDateTimeString(),
                    'settle_time' => $item->settle_time
                ];
            })
        ]);
    }

    //开票/收款
    public function ticket(Request $request) {
        $params = $request->all();

        $validator = Validator::make($params, [
            'id' => 'required|integer',
            'amount' => 'required|numeric',
            'annex' => 'required',
            'type' => 'required|in:1,2'
        ], [
            'id.required' => '请选择账单',
            'id.integer' => '账单错误',
            'amount.required' => '请输入金额',
            'amount.numeric' => '金额错误',
            'annex.required' => '请上传附件',
            'type.required' => '类型错误',
            'type.in' => '类型错误'
        ]);
    
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }

        $bill = PayBillModel::find($params['id']);

        if (!$bill) {
            return $this->error('账单不存在');
        }

        $auth = $request->get('auth');

        $ticket = new PayBillTicketModel();
        $ticket->pay_bill_id = $params['id'];
        $ticket->type = $params['type'];
        $ticket->amount = $params['amount'];
        $ticket->annex = $params['annex'];
        $ticket->created_admin_id = $auth->id;
        $ticket->save();

        return $this->success();
    }

    //修改账单 - 详情
    public function detail2($id){
        $bill = PayBillModel::find($id);
        if (!$bill) {
            return $this->error('数据不存在');
        }

        //基础信息
        $base = [
            'id' => $bill->id,
            'agent_name' => $bill->agent->name ?? '',
            'type' => AgentModel::TYPE_LIST[$item->agent->type??''] ?? '',
            'created_at' => $bill->created_at->toDateTimeString(),
            'amount' => $bill->amount,
            'sn' => $bill->sn,
            'remark' => $bill->remark,
        ];

        //收款列表
        $take_orders = TakeOrderModel::whereIn('id', $bill->take_order_ids->pluck('take_order_id'))->get();
        $list = $take_orders->map(function($item) use ($bill){
            $split_order_count = 0;
            foreach($item->orders as $order) {
                $split_order_count += $order->split_order_addr->count();
            } 

            $routes = RouteModel::whereIn('id', $item->flight->items->pluck('route_id'))
                ->pluck('name')->toArray();

            $flight_no = BaseFlightModel::whereIn('id', $item->flight->items->pluck('airline_flight_id'))
                ->pluck('flight_number')->toArray();

            $amount = 0;
            $recs = TakeOrderRecModel::where('take_order_id', $item->id)
                ->where('currency', $bill->currency)->get();
            foreach($recs as $rec) {
                if($rec->currency == $bill->currency) {
                    $amount += $rec->amount;
                }
            }

            return [
                'id' => $item->id,
                'sn' => $item->sn,
                'slipt_order_count' => $split_order_count,
                'order_count' => $item->orders->count(),
                'reality_weight' => $item->reality_weight,
                'route' => implode(',', $routes),
                'flight_no' => implode(',', $flight_no),
                'status_name' => TakeOrderModel::STATUS_MAPS[$item->status] ?? '',
                'currency' => $bill->currency,
                'amount' => $amount,
                'take_off_time' => $item->flight->take_off_time ?? '',
                'created_at' => $item->created_at->toDateTimeString(),
                'settle_time' => $item->settle_time,
                'take_order_id' => $item->id,
            ];
        });

        return $this->success([
            'base' => $base,
            'list' => $list,
        ]);

    }

    //修改账单
    public function update(Request $request, $id) {
        $bill = PayBillModel::find($id);
        if(!$bill) {
            return $this->error('账单不存在');
        }

        $remark = $request->input('remark', '');

        $bill->remark = $remark;
        $bill->save();

        return $this->success();
    }

    //撤出账单
    public function remove(Request $request) {
        $id = $request->input('id');
        $bill = PayBillModel::find($id);
        if(!$bill) {
            return $this->error('账单不存在');
        }

        $take_order_id = $request->input('take_order_id', '');
        $take_order = TakeOrderModel::find($take_order_id);
        if(!$take_order) {
            return $this->error('提单不存在');
        }

        if(!in_array($take_order_id, $bill->take_order_ids->pluck('take_order_id')->toArray())) {
            return $this->error('提单错误');
        }

        DB::transaction(function() use ($take_order, $bill){
            //修改提单id
            PayBillIdsModel::where('pay_bill_id', $bill->id)
                ->where('take_order_id', $take_order->id)->delete();

            //应付金额
            $amount = TakeOrderPayModel::where('take_order_id', $take_order->id)
                ->where('currency', $bill->currency)
                ->where('agent_id', $bill->agent_id)
                ->sum('amount');

            $bill->amount -= $amount;  //应收金额减去撤出去的应收金额

            $bill->save();

        });


        return $this->success();
    }
    

    //添加提单
    public function join(Request $request) {
        $id = $request->input('id');
        $bill = PayBillModel::find($id);
        if(!$bill) {
            return $this->error('账单不存在');
        }

        $take_order_ids = array_unique($request->input('take_order_ids', []));
        $take_orders = TakeOrderModel::whereIn('id',$take_order_ids)->get();

        foreach($take_orders as $take_order) {
            if(in_array($take_order->id, $bill->take_order_ids->pluck('take_order_id')->toArray())) {
                return $this->error('提单已在账单中');
            }
        }

        DB::transaction(function() use ($bill){
            foreach($bill->take_order_ids->pluck('take_order_id') as $take_order_id) {
                //应付金额
                $amount = TakeOrderPayModel::where('take_order_id', $take_order_id)
                    ->where('currency', $bill->currency)
                    ->where('agent_id', $bill->agent_id)
                    ->sum('amount');

                $bill->amount += $amount;
            }

            //修改提单id
            $ids = new PayBillIdsModel();
            $ids->pay_bill_id = $bill->id;
            $ids->take_order_id = $take_order_id;
            $ids->save();

        });

        return $this->success();
    }

    //修改结算重量
    public function set_weight(Request $request)  {
        $id = $request->input('id');
        $bill = PayBillModel::find($id);
        if(!$bill) {
            return $this->error('账单不存在');
        }

        $take_order_id = $request->input('take_order_id');
        $take_order = TakeOrderModel::find($take_order_id);
        if(!$take_order) {
            return $this->error('提单错误');
        }

        $weight = floatval($request->input('weight'));
        $take_order->reality_weight2 = $weight;
        $take_order->save();

        return $this->success();
    }


}
